home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 681 / term / source.lha / Console.c < prev    next >
C/C++ Source or Header  |  1992-05-09  |  27KB  |  1,659 lines

  1. /*
  2. **    $Id: Console.c,v 1.5 92/05/01 12:52:03 olsen Sta Locker: olsen $
  3. **    $Revision: 1.5 $
  4. **    $Date: 92/05/01 12:52:03 $
  5. **
  6. **    High-level console control routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Use a simple address trick instead of the predefined
  15.      * address in amiga.lib.
  16.      */
  17.  
  18. #ifndef custom
  19. #define custom (*(struct Custom *)0xDFF000)
  20. #endif    /* custom */
  21.  
  22.     /* The characters to abort parsing a control sequence. */
  23.  
  24. STATIC BYTE AbortTable[256] = 
  25. {
  26.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  27.     0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,
  28.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  29.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  30.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  31.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  32.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  33.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  34.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  35.     0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
  36.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  37.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  38.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  39.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  40.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  41.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  42. };
  43.  
  44.     /* StripSequence():
  45.      *
  46.      *    Strips a string from ESC and CSI introduced control
  47.      *    sequences.
  48.      */
  49.  
  50. STATIC LONG __regargs
  51. StripSequence(UBYTE *Src,UBYTE *Dst,LONG Length)
  52. {
  53.     STATIC BYTE    HasESC = FALSE,HasCSI = FALSE;
  54.     LONG        Size = 0;
  55.  
  56.     while(Length--)
  57.     {
  58.         if(*Src == 24 || *Src == 26)
  59.         {
  60.             HasESC = HasCSI = FALSE;
  61.  
  62.             Src++;
  63.  
  64.             continue;
  65.         }
  66.  
  67.         if(*Src == '\r')
  68.         {
  69.             Src++;
  70.  
  71.             continue;
  72.         }
  73.  
  74.         if(HasESC)
  75.         {
  76.             if(*Src == '[')
  77.             {
  78.                 HasESC = FALSE;
  79.                 HasCSI = TRUE;
  80.             }
  81.             else
  82.             {
  83.                 if(*Src >= '0')
  84.                     HasESC = FALSE;
  85.             }
  86.  
  87.             Src++;
  88.  
  89.             continue;
  90.         }
  91.  
  92.         if(HasCSI)
  93.         {
  94.             if(*Src >= '@')
  95.                 HasCSI = FALSE;
  96.  
  97.             Src++;
  98.  
  99.             continue;
  100.         }
  101.  
  102.         switch(*Src)
  103.         {
  104.             case ESC:    HasESC = TRUE;
  105.                     Src++;
  106.                     continue;
  107.  
  108.             case CSI:    HasCSI = TRUE;
  109.                     Src++;
  110.                     continue;
  111.  
  112.             default:    if(!ValidTab[*Src])
  113.                     {
  114.                         Src++;
  115.  
  116.                         continue;
  117.                     }
  118.  
  119.                     break;
  120.         }
  121.  
  122.         *Dst++ = *Src++;
  123.  
  124.         Size++;
  125.     }
  126.  
  127.     return(Size);
  128. }
  129.  
  130.     /* CaptureToFile(APTR Buffer,LONG Size):
  131.      *
  132.      *    Send data to the capture file.
  133.      */
  134.  
  135. VOID __regargs
  136. CaptureToFile(APTR Buffer,LONG Size)
  137. {
  138.     if(FileCapture && Size)
  139.     {
  140.         struct MenuItem    *SomeItem;
  141.  
  142.         if(BufferWrite(FileCapture,Buffer,Size) != Size)
  143.         {
  144.             BlockWindows();
  145.  
  146.                 /* We had an error writing to the file. */
  147.  
  148.             switch(MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_CAPTURE_FILE_TXT),LocaleString(MSG_CONSOLE_IGNORE_DISCARD_CLOSE_TXT),CaptureName))
  149.             {
  150.                 case 0:    break;
  151.  
  152.                 case 1:    BufferClose(FileCapture);
  153.  
  154.                     DeleteFile(CaptureName);
  155.  
  156.                     if(SomeItem = FindThisItem(MEN_CAPTUREDISK))
  157.                         SomeItem -> Flags &= ~CHECKED;
  158.  
  159.                     FileCapture = NULL;
  160.  
  161.                     break;
  162.  
  163.                 case 2:    BufferClose(FileCapture);
  164.  
  165.                     if(SomeItem = FindThisItem(MEN_CAPTUREDISK))
  166.                         SomeItem -> Flags &= ~CHECKED;
  167.  
  168.                     FileCapture = NULL;
  169.  
  170.                     if(!GetFileSize(CaptureName))
  171.                         DeleteFile(CaptureName);
  172.                     else
  173.                         SetProtection(CaptureName,FIBF_EXECUTE);
  174.  
  175.                     break;
  176.             }
  177.  
  178.             ReleaseWindows();
  179.         }
  180.     }
  181. }
  182.  
  183.     /* Capture(APTR Buffer,LONG Size):
  184.      *
  185.      *    Send the buffer contents to the display/disk capture.
  186.      */
  187.  
  188. VOID __regargs
  189. Capture(APTR Buffer,LONG Size)
  190. {
  191.     struct MenuItem *SomeItem;
  192.  
  193.         /* Send the filtered data to the capture file. */
  194.  
  195.     if(Config . CaptureFilter)
  196.         CaptureToFile(Buffer,Size);
  197.  
  198.         /* Store data in the log book. */
  199.  
  200.     if(!BufferFrozen)
  201.         StoreBuffer(Buffer,Size);
  202.  
  203.         /* Send the buffer to the printer. */
  204.  
  205.     if(PrinterCapture && Size)
  206.     {
  207.         if(!FWrite(PrinterCapture,Buffer,Size,1))
  208.         {
  209.             BlockWindows();
  210.  
  211.             if(!MyEasyRequest(Window,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  212.             {
  213.                 Close(PrinterCapture);
  214.  
  215.                 if(SomeItem = FindThisItem(MEN_CAPTUREPRINTER))
  216.                     SomeItem -> Flags &= ~CHECKED;
  217.  
  218.                 PrinterCapture = NULL;
  219.             }
  220.  
  221.             ReleaseWindows();
  222.         }
  223.     }
  224. }
  225.  
  226.     /* ClosePrinterCapture(BYTE Force):
  227.      *
  228.      *    Closes printer capture file.
  229.      */
  230.  
  231. VOID
  232. ClosePrinterCapture(BYTE Force)
  233. {
  234.     struct MenuItem *Item = FindThisItem(MEN_CAPTUREPRINTER);
  235.  
  236.     if(PrinterCapture)
  237.     {
  238.         if(ControllerActive && StandardPrinterCapture && !Force)
  239.             FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_TERMINAL_TRANSCRIPT_ENDING_TXT));
  240.  
  241.         if(Force)
  242.         {
  243.             Close(PrinterCapture);
  244.  
  245.             Item -> Flags &= ~CHECKED;
  246.  
  247.             PrinterCapture = NULL;
  248.  
  249.             StandardPrinterCapture = FALSE;
  250.         }
  251.     }
  252.  
  253.     ControllerActive = FALSE;
  254. }
  255.  
  256.     /* OpenPrinterCapture(BYTE Controller):
  257.      *
  258.      *    Opens printer capture file.
  259.      */
  260.  
  261. BYTE
  262. OpenPrinterCapture(BYTE Controller)
  263. {
  264.     if(PrinterCapture)
  265.     {
  266.         if(Controller && !ControllerActive)
  267.         {
  268.             ControllerActive = TRUE;
  269.  
  270.             FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_TERMINAL_TRANSCRIPT_FOLLOWS_TXT));
  271.         }
  272.  
  273.         return(TRUE);
  274.     }
  275.     else
  276.     {
  277.         struct MenuItem *Item = FindThisItem(MEN_CAPTUREPRINTER);
  278.  
  279.         if(PrinterCapture = Open("PRT:",MODE_NEWFILE))
  280.             Item -> Flags |= CHECKED;
  281.         else
  282.         {
  283.             Item -> Flags &= ~CHECKED;
  284.  
  285.             BlockWindows();
  286.  
  287.             MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_ERROR_OPENING_PRINTER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  288.  
  289.             ReleaseWindows();
  290.         }
  291.  
  292.         if(Controller)
  293.         {
  294.             ControllerActive    = TRUE;
  295.             StandardPrinterCapture    = FALSE;
  296.         }
  297.         else
  298.         {
  299.             StandardPrinterCapture = FALSE;
  300.  
  301.             if(ControllerActive)
  302.                 FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_USER_TERMINAL_TRANSCRIPT_FOLLOWS_TXT));
  303.         }
  304.  
  305.         if(PrinterCapture)
  306.             return(TRUE);
  307.         else
  308.             return(FALSE);
  309.     }
  310. }
  311.  
  312.     /* PrintRegion(WORD Top,WORD Bottom):
  313.      *
  314.      *    Print the contents of a screen region.
  315.      */
  316.  
  317. VOID
  318. PrintRegion(WORD Top,WORD Bottom)
  319. {
  320.     BPTR     SomeFile;
  321.     WORD     i,j;
  322.     UBYTE    *Buffer;
  323.  
  324.     if(PrinterCapture)
  325.     {
  326.         if(!FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_SCREEN_PRINTOUT_FOLLOWS_TXT)))
  327.         {
  328.             MyEasyRequest(Window,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  329.  
  330.             return;
  331.         }
  332.  
  333.         SomeFile = PrinterCapture;
  334.     }
  335.     else
  336.     {
  337.         if(!(SomeFile = Open("PRT:",MODE_NEWFILE)))
  338.         {
  339.             MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_PRINTER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  340.  
  341.             return;
  342.         }
  343.     }
  344.  
  345.     for(i = Top ; i < Bottom ; i++)
  346.     {
  347.         Buffer = &Raster[i * RasterWidth];
  348.  
  349.         j = LastColumn;
  350.  
  351.         while(j >= 0 && Buffer[j] == ' ')
  352.             j--;
  353.  
  354.         if(j >= 0)
  355.         {
  356.             if(!FWrite(SomeFile,Buffer,j + 1,1))
  357.                 break;
  358.         }
  359.  
  360.         if(!FWrite(SomeFile,"\n",1,1))
  361.             break;
  362.     }
  363.  
  364.     if(PrinterCapture)
  365.         FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_SCREEN_PRINTOUT_ENDING_TXT));
  366.     else
  367.         Close(SomeFile);
  368. }
  369.  
  370.     /* HandleCursor(UBYTE Char):
  371.      *
  372.      *    This routine handles the somewhat strange behaviour of
  373.      *    an assorted set of keys in VT100 applications mode.
  374.      */
  375.  
  376. BYTE __regargs
  377. HandleCursor(UBYTE Char)
  378. {
  379.     STATIC struct
  380.     {
  381.         UBYTE     Char;
  382.         UBYTE    *VanillaString;
  383.         UBYTE    *ApplicationString;
  384.     } Table[18] =
  385.     {
  386.         CUP,    "\033[A",    "\033OA",
  387.         CDN,    "\033[B",    "\033OB",
  388.         CFW,    "\033[C",    "\033OC",
  389.         CBK,    "\033[D",    "\033OD",
  390.  
  391.         '0',    "0",        "\033Op",
  392.         '1',    "1",        "\033Oq",
  393.         '2',    "2",        "\033Or",
  394.         '3',    "3",        "\033Os",
  395.         '4',    "4",        "\033Ot",
  396.         '5',    "5",        "\033Ou",
  397.         '6',    "6",        "\033Ov",
  398.         '7',    "7",        "\033Ow",
  399.         '8',    "8",        "\033Ox",
  400.         '9',    "9",        "\033Oy",
  401.         '-',    "-",        "\033Om",
  402.         '*',    "*",        "\033Ol",
  403.         '.',    ".",        "\033On",
  404.         '\r',    "\r",        "\033OM"
  405.     };
  406.  
  407.     BYTE i;
  408.  
  409.         /* Look for the cursor keys first. */
  410.  
  411.     for(i = 0 ; i < 4 ; i++)
  412.     {
  413.         if(Table[i] . Char == Char)
  414.         {
  415.             if(Config . CursorApp)
  416.                 SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
  417.             else
  418.                 SerWrite(Table[i] . VanillaString,strlen(Table[i] . VanillaString));
  419.  
  420.             return(TRUE);
  421.         }
  422.     }
  423.  
  424.         /* Then take a look at the numeric pad. */
  425.  
  426.     for(i = 4 ; i < 18 ; i++)
  427.     {
  428.         if(Table[i] . Char == Char)
  429.         {
  430.             if(Config . NumApp)
  431.                 SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
  432.             else
  433.             {
  434.                 if(i == 17)
  435.                 {
  436.                     switch(Config . SendCR)
  437.                     {
  438.                         case CR_IGNORE:    break;
  439.  
  440.                         case CR_ASCR:    SerWrite("\r",1);
  441.                                 break;
  442.  
  443.                         case CR_ASCRLF:    SerWrite("\r\n",2);
  444.                                 break;
  445.                     }
  446.                 }
  447.                 else
  448.                     SerWrite(Table[i] . VanillaString,strlen(Table[i] . VanillaString));
  449.             }
  450.  
  451.             return(TRUE);
  452.         }
  453.     }
  454.  
  455.     return(FALSE);
  456. }
  457.  
  458.     /* DoBackspace():
  459.      *
  460.      *    Special function: perform backspace.
  461.      */
  462.  
  463. VOID
  464. DoBackspace()
  465. {
  466.     Capture("\b",1);
  467.  
  468.     if(CursorX)
  469.     {
  470.         ClearCursor();
  471.  
  472.         CursorX--;
  473.  
  474.             /* If destructive, shift the remaining line
  475.              * one character to the right.
  476.              */
  477.  
  478.         if(Config . DestructiveBackspace)
  479.         {
  480.             WORD DeltaX,MinX;
  481.  
  482.             BackupRender();
  483.  
  484.             SetBPen(RPort,0);
  485.  
  486.             RasterEraseCharacters(1);
  487.  
  488.             if(Config . FontScale == SCALE_NORMAL)
  489.             {
  490.                 if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  491.                 {
  492.                     DeltaX    = 8;
  493.                     MinX    = CursorX << 3;
  494.                 }
  495.                 else
  496.                 {
  497.                     DeltaX    = 4;
  498.                     MinX    = CursorX << 2;
  499.                 }
  500.             }
  501.             else
  502.             {
  503.                 if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  504.                 {
  505.                     DeltaX    = 4;
  506.                     MinX    = CursorX << 2;
  507.                 }
  508.                 else
  509.                 {
  510.                     DeltaX    = 8;
  511.                     MinX    = CursorX << 3;
  512.                 }
  513.             }
  514.  
  515.             ScrollLineEraseCharacters(1);
  516.  
  517.             ScrollLineRaster(RPort,DeltaX,0,MinX,CursorY * 8,LastPixel,(CursorY + 1) * 8 - 1);
  518.  
  519.             BackupRender();
  520.         }
  521.  
  522.         SetCursor();
  523.     }
  524. }
  525.  
  526.     /* DoSomeBeep():
  527.      *
  528.      *    The real interface to the beep routine.
  529.      */
  530.  
  531. VOID
  532. DoSomeBeep()
  533. {
  534.         /* Handle the visual part. */
  535.  
  536.     if(Config . VisibleBell || Config . SystemBeep)
  537.     {
  538.         if(StatusProcess)
  539.             Signal(StatusProcess,SIGBREAKF_CTRL_D);
  540.     }
  541.  
  542.         /* Let it beep. */
  543.  
  544.     if(Config . AudibleBell)
  545.         Beep();
  546.  
  547.         /* Capture the bell. */
  548.  
  549.     if(!Config . CaptureFilter)
  550.         Capture("\a",1);
  551. }
  552.  
  553.     /* DoLF():
  554.      *
  555.      *    Special function: perform line feed.
  556.      */
  557.  
  558. VOID
  559. DoLF()
  560. {
  561.     if(Config . ReceiveLF == LF_ASLFCR)
  562.     {
  563.         ClearCursor();
  564.  
  565.         CursorX = 0;
  566.  
  567.         DownLine();
  568.  
  569.         SetCursor();
  570.  
  571.         Capture("\n",1);
  572.     }
  573.     else
  574.     {
  575.         if(Config . ReceiveLF == LF_ASLF)
  576.         {
  577.             ClearCursor();
  578.  
  579.             DownLine();
  580.  
  581.             SetCursor();
  582.         }
  583.     }
  584. }
  585.  
  586.     /* DoShiftIn():
  587.      *
  588.      *    Special function: Shift into graphics mode
  589.      */
  590.  
  591. VOID
  592. DoShiftIn()
  593. {
  594.     if(CharMode[1] == TABLE_GFX && GFX)
  595.         CurrentFont = GFX;
  596.  
  597.     if(CharMode[1] == TABLE_ASCII)
  598.     {
  599.         if(Config . Font == FONT_IBM && IBM)
  600.             CurrentFont = IBM;
  601.         else
  602.             CurrentFont = Topaz;
  603.     }
  604.  
  605.     SetFont(RPort,CurrentFont);
  606.  
  607.     Charset = 1;
  608. }
  609.  
  610.     /* DoShiftOut():
  611.      *
  612.      *    Special function: Shift out of graphics mode
  613.      */
  614.  
  615. VOID
  616. DoShiftOut()
  617. {
  618.     if(CharMode[0] == TABLE_GFX && GFX)
  619.         CurrentFont = GFX;
  620.  
  621.     if(CharMode[0] == TABLE_ASCII)
  622.     {
  623.         if(Config . Font == FONT_IBM && IBM)
  624.             CurrentFont = IBM;
  625.         else
  626.             CurrentFont = Topaz;
  627.     }
  628.  
  629.     SetFont(RPort,CurrentFont);
  630.  
  631.     Charset = 0;
  632. }
  633.  
  634.     /* DoIgnore():
  635.      *
  636.      *    Special function: don't do anything.
  637.      */
  638.  
  639. VOID
  640. DoIgnore()
  641. {
  642. }
  643.  
  644.     /* DoCR_LF():
  645.      *
  646.      *    Special function: perform carriage return and line feed.
  647.      */
  648.  
  649. VOID
  650. DoCR_LF()
  651. {
  652.     ClearCursor();
  653.  
  654.     CursorX = 0;
  655.  
  656.     DownLine();
  657.  
  658.     SetCursor();
  659.  
  660.     Capture("\n",1);
  661. }
  662.  
  663.     /* DoFF():
  664.      *
  665.      *    Special function: perform form feed.
  666.      */
  667.  
  668. VOID
  669. DoFF()
  670. {
  671.     if(Config . NewLine)
  672.     {
  673.         CursorX = 0;
  674.  
  675.         DoCR_LF();
  676.     }
  677.     else
  678.     {
  679.         EraseScreen("2");
  680.  
  681.         ClearCursor();
  682.  
  683.         CursorX = CursorY = 0;
  684.  
  685.         SetCursor();
  686.  
  687.         Capture("\n",1);
  688.     }
  689. }
  690.  
  691.     /* DoLF_FF_VT():
  692.      *
  693.      *    Special function: handle line feed, form feed and vertical
  694.      *    tab.
  695.      */
  696.  
  697. VOID
  698. DoLF_FF_VT()
  699. {
  700.     if(Config . NewLine)
  701.         DoCR_LF();
  702.     else
  703.         DoLF();
  704. }
  705.  
  706.     /* DoCR():
  707.      *
  708.      *    Special function: handle carriage return.
  709.      */
  710.  
  711. VOID
  712. DoCR()
  713. {
  714.     if(Config . NewLine || Config . ReceiveCR == CR_ASCRLF)
  715.         DoCR_LF();
  716.     else
  717.     {
  718.         if(Config . ReceiveCR == CR_ASCR)
  719.         {
  720.             ClearCursor();
  721.  
  722.             CursorX = 0;
  723.  
  724.             SetCursor();
  725.  
  726.             Capture("\n",1);
  727.         }
  728.     }
  729. }
  730.  
  731.     /* DoTab():
  732.      *
  733.      *    Special function: handle tab, move cursor to next
  734.      *    tab stop.
  735.      */
  736.  
  737. VOID
  738. DoTab()
  739. {
  740.     WORD Column;
  741.  
  742.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  743.         Column = LastColumn;
  744.     else
  745.         Column = ((LastColumn + 1) / 2) - 1;
  746.  
  747.     ClearCursor();
  748.  
  749.     if(Config . AutoWrap)
  750.     {
  751.         if(CursorX >= LastColumn)
  752.         {
  753.             CursorX = 0;
  754.  
  755.             DownLine();
  756.         }
  757.         else
  758.         {
  759.             while(CursorX < Column)
  760.             {
  761.                 CursorX++;
  762.  
  763.                 if(TabStops[CursorX])
  764.                     break;
  765.             }
  766.         }
  767.     }
  768.     else
  769.     {
  770.         while(CursorX < Column)
  771.         {
  772.             CursorX++;
  773.  
  774.             if(TabStops[CursorX])
  775.                 break;
  776.         }
  777.     }
  778.  
  779.     SetCursor();
  780.  
  781.     Capture("\t",1);
  782. }
  783.  
  784.     /* DoEnq():
  785.      *
  786.      *    Special function: send answerback message.
  787.      */
  788.  
  789. VOID
  790. DoEnq()
  791. {
  792.     if(Config . AnswerBack[0])
  793.         SerialCommand(Config . AnswerBack);
  794. }
  795.  
  796.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  797.      *
  798.      *    Text output, if necessary switching from gfx font
  799.      *    to current default font.
  800.      */
  801.  
  802. VOID __regargs
  803. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  804. {
  805.     BYTE Mode = 1;
  806.  
  807.     while(Length--)
  808.     {
  809.         if(GfxTable[*Buffer] == Mode)
  810.             Text(RPort,Buffer++,1);
  811.         else
  812.         {
  813.             if(Mode)
  814.             {
  815.                 if(Config . Font == FONT_IBM && IBM)
  816.                     SetFont(RPort,IBM);
  817.                 else
  818.                     SetFont(RPort,Topaz);
  819.             }
  820.             else
  821.                 SetFont(RPort,GFX);
  822.  
  823.             Mode ^= 1;
  824.  
  825.             Text(RPort,Buffer++,1);
  826.         }
  827.     }
  828.  
  829.     if(!Mode)
  830.         SetFont(RPort,GFX);
  831. }
  832.  
  833.     /* SpillTheBeans(UBYTE *Buffer,LONG Size):
  834.      *
  835.      *    Output a buffer of given size to the terminal
  836.      *    window.
  837.      */
  838.  
  839. STATIC VOID __regargs
  840. SpillTheBeans(UBYTE *Buffer,LONG Size)
  841. {
  842.     if(ControllerActive)
  843.     {
  844.         if(Size)
  845.         {
  846.             if(!FWrite(PrinterCapture,Buffer,Size,1))
  847.             {
  848.                 BlockWindows();
  849.  
  850.                 if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  851.                     ClosePrinterCapture(TRUE);
  852.  
  853.                 ReleaseWindows();
  854.             }
  855.         }
  856.     }
  857.     else
  858.     {
  859.         UBYTE    Scale,CharScale;
  860.         WORD    Offset,LastChar;
  861.  
  862.             /* Reposition the cursor and turn it off. */
  863.  
  864.         ClearCursor();
  865.  
  866.         Scale = RasterAttr[CursorY];
  867.  
  868.         if(Config . FontScale == SCALE_HALF)
  869.         {
  870.             switch(Scale)
  871.             {
  872.                 case SCALE_ATTR_TOP2X:
  873.                 case SCALE_ATTR_BOT2X:
  874.                 case SCALE_ATTR_NORMAL:    CharScale    = TRUE;
  875.                             LastChar    = LastColumn;
  876.                             break;
  877.  
  878.                 case SCALE_ATTR_2X:    CharScale    = FALSE;
  879.                             LastChar    = LastColumn;
  880.                             break;
  881.             }
  882.         }
  883.         else
  884.         {
  885.             switch(Scale)
  886.             {
  887.                 case SCALE_ATTR_TOP2X:
  888.                 case SCALE_ATTR_BOT2X:
  889.                 case SCALE_ATTR_2X:    CharScale    = TRUE;
  890.                             LastChar    = ((LastColumn + 1) / 2) - 1;
  891.                             break;
  892.  
  893.                 case SCALE_ATTR_NORMAL:    CharScale    = FALSE;
  894.                             LastChar    = LastColumn;
  895.                             break;
  896.             }
  897.         }
  898.  
  899.         if(CurrentFont == GFX)
  900.         {
  901.                 /* Do we still have a character in the
  902.                  * magnificient buffer?
  903.                  */
  904.  
  905.             while(Size)
  906.             {
  907.                 /* Cursor is positioned at
  908.                  * the right hand side of the
  909.                  * display. If auto-wrap is
  910.                  * enabled, perform some
  911.                  * kind of CR/LF, else leave
  912.                  * the cursor where it is and
  913.                  * quit the show.
  914.                  */
  915.  
  916.                 if(CursorX > LastChar)
  917.                 {
  918.                         /* Wrap cursor. */
  919.  
  920.                     if(Config . AutoWrap)
  921.                     {
  922.                             /* Move to beginning of next line. */
  923.  
  924.                         CursorX = 0;
  925.  
  926.                         DownLine();
  927.  
  928.                         Capture("\n",1);
  929.  
  930.                         Scale = SCALE_ATTR_NORMAL;
  931.  
  932.                         CharScale = (Config . FontScale == SCALE_NORMAL) ? FALSE : TRUE;
  933.  
  934.                         LastChar = LastColumn;
  935.  
  936.                             /* Reposition cursor, don't redraw it. */
  937.  
  938.                         ClipBlitCursor(FALSE,TRUE);
  939.                     }
  940.                     else
  941.                     {
  942.                             /* Stop the cursor. */
  943.  
  944.                         CursorX = LastChar;
  945.  
  946.                         Capture(Buffer,Size);
  947.  
  948.                             /* Make it reappear. */
  949.  
  950.                         SetCursor();
  951.  
  952.                         return;
  953.                     }
  954.                 }
  955.  
  956.                 if(CursorX <= LastChar)
  957.                 {
  958.                         /* We won't have to take
  959.                          * care of characters to shift.
  960.                          * We'll collect as many
  961.                          * characters in the buffer as will
  962.                          * fit into the current line
  963.                          * and print them.
  964.                          */
  965.  
  966.                     if((Offset = LastChar + 1 - CursorX) > Size)
  967.                     {
  968.                         Offset = Size;
  969.  
  970.                         if(Config . InsertChar)
  971.                         {
  972.                             RasterShiftChar(Offset);
  973.  
  974.                             ScrollLineShiftChar(Offset);
  975.  
  976.                             ShiftChar(Offset);
  977.                         }
  978.                     }
  979.  
  980.                     RasterPutString(Buffer,Offset);
  981.  
  982.                     ScrollLinePutString(Offset);
  983.  
  984.                     if(CharScale)
  985.                         PrintScaled(Buffer,Offset,Scale);
  986.                     else
  987.                         GfxText(RPort,Buffer,Offset);
  988.  
  989.                     Capture(Buffer,Offset);
  990.  
  991.                     Buffer    += Offset;
  992.  
  993.                     Size    -= Offset;
  994.  
  995.                     CursorX    += Offset;
  996.                 }
  997.             }
  998.         }
  999.         else
  1000.         {
  1001.                 /* Do we still have a character in the
  1002.                  * magnificient buffer?
  1003.                  */
  1004.  
  1005.             while(Size)
  1006.             {
  1007.                 /* Cursor is positioned at
  1008.                  * the right hand side of the
  1009.                  * display. If auto-wrap is
  1010.                  * enabled, perform some
  1011.                  * kind of CR/LF, else leave
  1012.                  * the cursor where it is and
  1013.                  * quit the show.
  1014.                  */
  1015.  
  1016.                 if(CursorX > LastChar)
  1017.                 {
  1018.                         /* Wrap cursor. */
  1019.  
  1020.                     if(Config . AutoWrap)
  1021.                     {
  1022.                             /* Move to beginning of next line. */
  1023.  
  1024.                         CursorX = 0;
  1025.  
  1026.                         DownLine();
  1027.  
  1028.                         Capture("\n",1);
  1029.  
  1030.                         Scale = SCALE_ATTR_NORMAL;
  1031.  
  1032.                         CharScale = (Config . FontScale == SCALE_NORMAL) ? FALSE : TRUE;
  1033.  
  1034.                         LastChar = LastColumn;
  1035.  
  1036.                             /* Reposition cursor, don't redraw it. */
  1037.  
  1038.                         ClipBlitCursor(FALSE,TRUE);
  1039.                     }
  1040.                     else
  1041.                     {
  1042.                             /* Stop the cursor. */
  1043.  
  1044.                         CursorX = LastChar;
  1045.  
  1046.                         Capture(Buffer,Size);
  1047.  
  1048.                             /* Make it reappear. */
  1049.  
  1050.                         SetCursor();
  1051.  
  1052.                         return;
  1053.                     }
  1054.                 }
  1055.  
  1056.                 if(CursorX <= LastChar)
  1057.                 {
  1058.                         /* We won't have to take
  1059.                          * care of characters to shift.
  1060.                          * We'll collect as many
  1061.                          * characters in the buffer as will
  1062.                          * fit into the current line
  1063.                          * and print them.
  1064.                          */
  1065.  
  1066.                     if((Offset = LastChar + 1 - CursorX) > Size)
  1067.                     {
  1068.                         Offset = Size;
  1069.  
  1070.                         if(Config . InsertChar)
  1071.                         {
  1072.                             RasterShiftChar(Offset);
  1073.  
  1074.                             ScrollLineShiftChar(Offset);
  1075.  
  1076.                             ShiftChar(Offset);
  1077.                         }
  1078.                     }
  1079.  
  1080.                     RasterPutString(Buffer,Offset);
  1081.  
  1082.                     ScrollLinePutString(Offset);
  1083.  
  1084.                     if(CharScale)
  1085.                         PrintScaled(Buffer,Offset,Scale);
  1086.                     else
  1087.                         Text(RPort,Buffer,Offset);
  1088.  
  1089.                     Capture(Buffer,Offset);
  1090.  
  1091.                     Buffer    += Offset;
  1092.  
  1093.                     Size    -= Offset;
  1094.  
  1095.                     CursorX    += Offset;
  1096.                 }
  1097.             }
  1098.         }
  1099.  
  1100.             /* Make the cursor reappear. */
  1101.  
  1102.         SetCursor();
  1103.     }
  1104. }
  1105.  
  1106.     /* ConWrite(APTR Buffer,LONG Size):
  1107.      *
  1108.      *    Write a string to the console window.
  1109.      */
  1110.  
  1111. VOID __regargs
  1112. ConWrite(APTR Buffer,LONG Size)
  1113. {
  1114.     STATIC UBYTE     StringBuffer[200],BufSize = 0;
  1115.     UBYTE        *Char = Buffer;
  1116.  
  1117.         /* Run down the buffer. */
  1118.  
  1119.     while(Size--)
  1120.     {
  1121.             /* Are we parsing a control sequence? */
  1122.  
  1123.         if(InSequence)
  1124.         {
  1125.             if(AbortTable[*Char])
  1126.             {
  1127.                 DoCancel();
  1128.  
  1129.                 if(*Char == ESC || *Char == CSI)
  1130.                     InSequence = TRUE;
  1131.             }
  1132.             else
  1133.             {
  1134.                     /* See if we are already done. */
  1135.  
  1136.                 InSequence = ParseCode(*Char++);
  1137.             }
  1138.         }
  1139.         else
  1140.         {
  1141.                 /* This looks like a control sequence
  1142.                  * introducing character.
  1143.                  */
  1144.  
  1145.             if(*Char == ESC || *Char == CSI)
  1146.             {
  1147.                 if(BufSize)
  1148.                 {
  1149.                     SpillTheBeans(&StringBuffer[0],BufSize);
  1150.  
  1151.                     BufSize = 0;
  1152.                 }
  1153.  
  1154.                     /* So we're in TTY mode,
  1155.                      * escape the `escape' character
  1156.                      * and continue.
  1157.                      */
  1158.  
  1159.                 if(Config . Emulation == EMULATION_TTY)
  1160.                 {
  1161.                     StringBuffer[BufSize++] = '^';
  1162.                     StringBuffer[BufSize++] = '[';
  1163.                 }
  1164.                 else
  1165.                 {
  1166.                     if(*Char == ESC)
  1167.                         InSequence = TRUE;
  1168.                     else
  1169.                         CSIFake();
  1170.                 }
  1171.  
  1172.                 Char++;
  1173.             }
  1174.             else
  1175.             {
  1176.                     /* Stuff the character into
  1177.                      * the buffer.
  1178.                      */
  1179.  
  1180.                 StringBuffer[BufSize++] = *Char++;
  1181.  
  1182.                     /* If buffer is full, spill it. */
  1183.  
  1184.                 if(BufSize == 200)
  1185.                 {
  1186.                     SpillTheBeans(&StringBuffer[0],BufSize);
  1187.  
  1188.                     BufSize = 0;
  1189.                 }
  1190.             }
  1191.         }
  1192.     }
  1193.  
  1194.         /* Any characters in the buffer we didn't process yet? */
  1195.  
  1196.     if(!InSequence && BufSize)
  1197.     {
  1198.         SpillTheBeans(&StringBuffer[0],BufSize);
  1199.  
  1200.         BufSize = 0;
  1201.     }
  1202. }
  1203.  
  1204.     /* ConProcess(UBYTE *String,LONG Size):
  1205.      *
  1206.      *    Process the contents of a string to be sent to the
  1207.      *    console window.
  1208.      */
  1209.  
  1210. VOID __regargs
  1211. ConProcess(UBYTE *String,LONG Size)
  1212. {
  1213.     LONG i;
  1214.  
  1215.         /* If the capture filter happens to be disabled, write the
  1216.          * raw data.
  1217.          */
  1218.  
  1219.     if(!Config . CaptureFilter)
  1220.         CaptureToFile(String,Size);
  1221.  
  1222.         /* Oh dear, an external emulation will take care of
  1223.          * displaying the data so we will need to make sure
  1224.          * that the data flow filter and the capture streams
  1225.          * are properly fed.
  1226.          */
  1227.  
  1228.     if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL)
  1229.     {
  1230.             /* Feed the flow filter... */
  1231.  
  1232.         if(Config . StripBit8)
  1233.         {
  1234.             for(i = 0 ; i < Size ; i++)
  1235.                 FlowFilter(String[i] & 0x7F);
  1236.         }
  1237.         else
  1238.         {
  1239.             for(i = 0 ; i < Size ; i++)
  1240.                 FlowFilter(String[i]);
  1241.         }
  1242.  
  1243.             /* Are we to output data? */
  1244.  
  1245.         if(!Quiet)
  1246.         {
  1247.             XEmulatorWrite(XEM_IO,String,Size);
  1248.  
  1249.                 /* Build another string to contain
  1250.                  * the pure ASCII contents, i.e.
  1251.                  * not including any ESC control
  1252.                  * sequences.
  1253.                  */
  1254.  
  1255.             if(StripBuffer)
  1256.             {
  1257.                 XEM_HostData . Source        = String;
  1258.                 XEM_HostData . Destination    = StripBuffer;
  1259.  
  1260.                 if(i = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  1261.                     Capture(StripBuffer,i);
  1262.             }
  1263.         }
  1264.     }
  1265.     else
  1266.     {
  1267.         LONG j;
  1268.  
  1269.             /* If the eighth bit is to be stripped from incoming
  1270.              * characters, let's process the whole stuff
  1271.              * in a different loop... (and that's all for the
  1272.              * sake of speed).
  1273.              */
  1274.  
  1275.         if(Config . StripBit8)
  1276.         {
  1277.                 /* In quiet mode no characters are echoed to the
  1278.                  * console window, they are just passed through
  1279.                  * the data flow filter. Usually, this mode is
  1280.                  * enabled by the dial panel.
  1281.                  */
  1282.  
  1283.             if(Quiet)
  1284.             {
  1285.                 for(i = 0 ; i < Size ; i++)
  1286.                     FlowFilter(String[i] & 0x7F);
  1287.             }
  1288.             else
  1289.             {
  1290.                 UBYTE c;
  1291.  
  1292.                     /* Check which font we are in, if other than Topaz
  1293.                      * the only invalid char is a Null (0) which will
  1294.                      * display as a space if let to continue.
  1295.                      */
  1296.  
  1297.                 if(Config . Font == FONT_TOPAZ)
  1298.                 {
  1299.                     for(i = 0, j = 0 ; i < Size ; i++)
  1300.                     {
  1301.                         c = String[i] & 0x7F;
  1302.  
  1303.                         FlowFilter(c);
  1304.  
  1305.                         if(IsPrintable(c))
  1306.                         {
  1307.                             /* This character is associated with a
  1308.                              * special function (bell, xon, xoff, etc.).
  1309.                              */
  1310.  
  1311.                             if(SpecialMap[c] != -1)
  1312.                             {
  1313.                                 if(j)
  1314.                                 {
  1315.                                     ConWrite(SharedBuffer,j);
  1316.  
  1317.                                     j = 0;
  1318.                                 }
  1319.  
  1320.                                 SpecialKeys[SpecialMap[c]] . Routine();
  1321.                             }
  1322.                             else
  1323.                             {
  1324.                                 /* Put the character into the buffer
  1325.                                  * and flush it if necessary.
  1326.                                  */
  1327.  
  1328.                                 SharedBuffer[j++] = c;
  1329.  
  1330.                                 if(j == 512)
  1331.                                 {
  1332.                                     ConWrite(SharedBuffer,j);
  1333.  
  1334.                                     j = 0;
  1335.                                 }
  1336.                             }
  1337.                         }
  1338.                     }
  1339.                 }
  1340.                 else
  1341.                 {
  1342.                     for(i = 0, j = 0 ; i < Size ; i++)
  1343.                     {
  1344.                         if(c = (String[i] & 0x7F))
  1345.                         {
  1346.                             FlowFilter(c);
  1347.  
  1348.                             /* This character is associated with a
  1349.                              * special function (bell, xon, xoff, etc.).
  1350.                              */
  1351.  
  1352.                             if(SpecialMap[c] != -1)
  1353.                             {
  1354.                                 if(j)
  1355.                                 {
  1356.                                     ConWrite(SharedBuffer,j);
  1357.  
  1358.                                     j = 0;
  1359.                                 }
  1360.  
  1361.                                 SpecialKeys[SpecialMap[c]] . Routine();
  1362.                             }
  1363.                             else
  1364.                             {
  1365.                                 /* Put the character into the buffer
  1366.                                  * and flush it if necessary.
  1367.                                  */
  1368.  
  1369.                                 SharedBuffer[j++] = c;
  1370.  
  1371.                                 if(j == 512)
  1372.                                 {
  1373.                                     ConWrite(SharedBuffer,j);
  1374.  
  1375.                                     j = 0;
  1376.                                 }
  1377.                             }
  1378.                         }
  1379.                     }
  1380.                 }
  1381.  
  1382.                 if(j)
  1383.                     ConWrite(SharedBuffer,j);
  1384.             }
  1385.         }
  1386.         else
  1387.         {
  1388.             if(Quiet)
  1389.             {
  1390.                 for(i = 0 ; i < Size ; i++)
  1391.                     FlowFilter(String[i]);
  1392.             }
  1393.             else
  1394.             {
  1395.                 UBYTE c;
  1396.  
  1397.                 if(Config . Font == FONT_TOPAZ)
  1398.                 {
  1399.                     for(i = 0, j = 0 ; i < Size ; i++)
  1400.                     {
  1401.                         c = String[i];
  1402.  
  1403.                         FlowFilter(c);
  1404.  
  1405.                         if(IsPrintable(c))
  1406.                         {
  1407.                             if(SpecialMap[c] != -1)
  1408.                             {
  1409.                                 if(j)
  1410.                                 {
  1411.                                     ConWrite(SharedBuffer,j);
  1412.  
  1413.                                     j = 0;
  1414.                                 }
  1415.  
  1416.                                 SpecialKeys[SpecialMap[c]] . Routine();
  1417.                             }
  1418.                             else
  1419.                             {
  1420.                                 SharedBuffer[j++] = c;
  1421.  
  1422.                                 if(j == 512)
  1423.                                 {
  1424.                                     ConWrite(SharedBuffer,j);
  1425.  
  1426.                                     j = 0;
  1427.                                 }
  1428.                             }
  1429.                         }
  1430.                     }
  1431.                 }
  1432.                 else
  1433.                 {
  1434.                     for(i = 0, j = 0 ; i < Size ; i++)
  1435.                     {
  1436.                         if(c = String[i])
  1437.                         {
  1438.                             FlowFilter(c);
  1439.  
  1440.                             if(SpecialMap[c] != -1)
  1441.                             {
  1442.                                 if(j)
  1443.                                 {
  1444.                                     ConWrite(SharedBuffer,j);
  1445.  
  1446.                                     j = 0;
  1447.                                 }
  1448.  
  1449.                                 SpecialKeys[SpecialMap[c]] . Routine();
  1450.                             }
  1451.                             else
  1452.                             {
  1453.                                 SharedBuffer[j++] = c;
  1454.  
  1455.                                 if(j == 512)
  1456.                                 {
  1457.                                     ConWrite(SharedBuffer,j);
  1458.  
  1459.                                     j = 0;
  1460.                                 }
  1461.                             }
  1462.                         }
  1463.                     }
  1464.                 }
  1465.  
  1466.                 if(j)
  1467.                     ConWrite(SharedBuffer,j);
  1468.             }
  1469.         }
  1470.     }
  1471. }
  1472.  
  1473.     /* ConWrites(UBYTE *String,...):
  1474.      *
  1475.      *    Output a string to the console.
  1476.      */
  1477.  
  1478. VOID __stdargs
  1479. ConWrites(UBYTE *String,...)
  1480. {
  1481.     va_list    VarArgs;
  1482.  
  1483.     va_start(VarArgs,String);
  1484.     VSPrintf(SharedBuffer,String,VarArgs);
  1485.     va_end(VarArgs);
  1486.  
  1487.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  1488. }
  1489.  
  1490.     /* KeyConvert(struct IntuiMessage *Massage,UBYTE *Buffer):
  1491.      *
  1492.      *    Convert a raw key information according to the
  1493.      *    current keymap settings.
  1494.      */
  1495.  
  1496. UBYTE __regargs
  1497. KeyConvert(struct IntuiMessage *Massage,UBYTE *Buffer,LONG *Len)
  1498. {
  1499.     if(Buffer)
  1500.         Buffer[0] = 0;
  1501.  
  1502.     if(Len)
  1503.         *Len = 0;
  1504.  
  1505.     if(Massage -> Class == IDCMP_RAWKEY)
  1506.     {
  1507.             /* These are the sequences mapped to special
  1508.              * control keys (cursor keys, function keys,
  1509.              * the help key).
  1510.              */
  1511.  
  1512.         STATIC struct
  1513.         {
  1514.             UBYTE *RawCode;
  1515.             UBYTE Result;
  1516.         } ConversionTable[16] =
  1517.         {
  1518.             (UBYTE *)"A",    CUP,
  1519.             (UBYTE *)"B",    CDN,
  1520.             (UBYTE *)"C",    CFW,
  1521.             (UBYTE *)"D",    CBK,
  1522.  
  1523.             (UBYTE *)"?~",    HLP,
  1524.  
  1525.             (UBYTE *)"0~",    FN1,
  1526.             (UBYTE *)"1~",    FN2,
  1527.             (UBYTE *)"2~",    FN3,
  1528.             (UBYTE *)"3~",    FN4,
  1529.             (UBYTE *)"4~",    FN5,
  1530.             (UBYTE *)"5~",    FN6,
  1531.             (UBYTE *)"6~",    FN7,
  1532.             (UBYTE *)"7~",    FN8,
  1533.             (UBYTE *)"8~",    FN9,
  1534.             (UBYTE *)"9~",    F10
  1535.         };
  1536.  
  1537.         STATIC UBYTE SeqLens[16] = {1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  1538.  
  1539.             /* Key was pressed, not released. */
  1540.  
  1541.         if(!(Massage -> Code & IECODE_UP_PREFIX))
  1542.         {
  1543.             UBYTE    ConvertBuffer[257],i;
  1544.             ULONG    Qualifier = Massage -> Qualifier;
  1545.             LONG    Actual;
  1546.  
  1547.                 /* If it's a function key clear the qualifier. */
  1548.  
  1549.             if(Massage -> Code >= 80 && Massage -> Code <= 89)
  1550.                 Qualifier = NULL;
  1551.  
  1552.                 /* Convert the key. */
  1553.  
  1554.             FakeInputEvent -> ie_Code        = Massage -> Code;
  1555.             FakeInputEvent -> ie_Qualifier        = Qualifier;
  1556.             FakeInputEvent -> ie_position . ie_addr    = *((APTR *)Massage -> IAddress);
  1557.  
  1558.             if((Actual = RawKeyConvert(FakeInputEvent,(UBYTE *)ConvertBuffer,256,KeyMap)) > 0)
  1559.             {
  1560.                 if(ConvertBuffer[0])
  1561.                 {
  1562.                     if(Config . SwapBSDelete)
  1563.                     {
  1564.                         for(i = 0 ; i < Actual ; i++)
  1565.                         {
  1566.                             if(ConvertBuffer[i] == BKS)
  1567.                                 ConvertBuffer[i] = DEL;
  1568.                             else
  1569.                             {
  1570.                                 if(ConvertBuffer[i] == DEL)
  1571.                                     ConvertBuffer[i] = BKS;
  1572.                             }
  1573.                         }
  1574.                     }
  1575.  
  1576.                     if(Len)
  1577.                     {
  1578.                         if(Actual == 1 && (Qualifier & IEQUALIFIER_CONTROL))
  1579.                         {
  1580.                             if(ConvertBuffer[0] == '@' || ConvertBuffer[0] == ' ')
  1581.                             {
  1582.                                 ConvertBuffer[0] = Buffer[0] = 0;
  1583.  
  1584.                                 *Len = 1;
  1585.                             }
  1586.                             else
  1587.                             {
  1588.                                 *Len = Actual;
  1589.  
  1590.                                 if(Buffer)
  1591.                                     memcpy(Buffer,ConvertBuffer,Actual);
  1592.                             }
  1593.                         }
  1594.                         else
  1595.                         {
  1596.                             *Len = Actual;
  1597.  
  1598.                             memcpy(Buffer,ConvertBuffer,Actual);
  1599.                         }
  1600.                     }
  1601.                     else
  1602.                     {
  1603.                         if(Buffer)
  1604.                             memcpy(Buffer,ConvertBuffer,Actual);
  1605.                     }
  1606.  
  1607.                         /* Translated sequence starts
  1608.                          * with a CSI, let's have a look
  1609.                          * at the associated control
  1610.                          * key.
  1611.                          */
  1612.  
  1613.                     if(ConvertBuffer[0] == CSI)
  1614.                     {
  1615.                         for(i = 0 ; i < sizeof(SeqLens) ; i++)
  1616.                         {
  1617.                             if(!Strnicmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  1618.                             {
  1619.                                 ConvertBuffer[0] = ConversionTable[i] . Result;
  1620.  
  1621.                                 if(Buffer)
  1622.                                 {
  1623.                                     Buffer[0] = ConversionTable[i] . Result;
  1624.                                     Buffer[1] = 0;
  1625.  
  1626.                                     if(Len)
  1627.                                         *Len = 1;
  1628.                                 }
  1629.  
  1630.                                 break;
  1631.                             }
  1632.                         }
  1633.                     }
  1634.  
  1635.                     return(ConvertBuffer[0]);
  1636.                 }
  1637.             }
  1638.  
  1639.                 /* If nothing came from the key conversion,
  1640.                  * check for shift-tab.
  1641.                  */
  1642.  
  1643.             if(Massage -> Code == 66 && (Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)))
  1644.             {
  1645.                 *Len = 2;
  1646.  
  1647.                 strcpy(ConvertBuffer,"\33\t");
  1648.  
  1649.                 if(Buffer)
  1650.                     memcpy(Buffer,ConvertBuffer,2);
  1651.  
  1652.                 return(ConvertBuffer[0]);
  1653.             }
  1654.         }
  1655.     }
  1656.  
  1657.     return(0);
  1658. }
  1659.